
package atm.main;

import java.util.Scanner;

import atm.components.AtmEngine;
import atm.model.CreditCardVerificationStatus;
import atm.model.PinCodeVerificationStatus;
import atm.model.WithdrawStatus;
import atm.utilities.ValidationUtilities;

public class Main {

	private static AtmEngine atmEngine = new AtmEngine();

	private static Scanner scan = new Scanner(System.in);

	public static void main(String[] args) {

		// ATM is idling - it never shuts down and it can handle as many customers as needed
		while (true) {

			System.out.println(">> UI: ATM is idle.");
			// By pressing a key on keyboard we simulate that customer puts a card into the reader...
			System.out.println(">> UI: Press Enter to insert credit card...");
			scan.nextLine();

			// ... and this is a sign that ATM should start transaction.
			boolean transactionStarted = atmEngine.startTransacation();

			if (transactionStarted) {
				// Let's read the credit card now
				boolean cardReadSuccessfully = atmEngine.readCreditCard();

				// If credit card was read successfully within 3 times, transaction continues
				if (cardReadSuccessfully) {

					// Let's check printer status. If it is not operable, we need to ask user if he can live with that
					boolean printerOk = atmEngine.checkPrinter();
					boolean userWantsToContinueWithoutPrinter = true;
					if (!printerOk) {
						System.out.println(">> UI: Printer is not operating. If you want to continue without confirmations press 'y'. ");
						String keyPressed = scan.next();
						scan.nextLine();
						if (keyPressed != "y") {
							userWantsToContinueWithoutPrinter = true;
						}
					}

					// If printer is operating or user agreed that he will not get confirmations we continue
					if (printerOk || !printerOk && userWantsToContinueWithoutPrinter) {
						// Credit card will now be validated with bank
						CreditCardVerificationStatus creditCardVerificationStatus = atmEngine.verifyCreditCard();

						// If verification was successful then user can continue with transaction
						if (creditCardVerificationStatus == CreditCardVerificationStatus.OK) {
							// Let's read the pinCode
							PinCodeVerificationStatus pinCodeVerificationStatus = ReadPinCode();

							if (pinCodeVerificationStatus == PinCodeVerificationStatus.OK) {
								// If the pincode is correct customer can withdraw money
								WithDrawAmount();

								// It does not really matter what the outcome of the operation is. Lets thank this guy for using our ATM (
								// ＾◡＾)
								System.out.println(">> UI: Thank you for using this ATM. You are welcomed to take more cash again!");
							} else if (pinCodeVerificationStatus == PinCodeVerificationStatus.FAILED_CARD_LOCKED) {
								// Or else if user locked his card by entering PIN too many times we end the transaction
								System.out
								        .println(">> UI: You failed to enter PIN code too many times. Your card will be withheld. Please contact your bank.");
							}

						} else if (creditCardVerificationStatus == CreditCardVerificationStatus.INVALID) {
							// Credit card is invalid user cannot continue with transaction and he will get his card back
							System.out.println(">> UI: Your card is invalid. Your card will be ejected now. Please contact your bank.");
						} else if (creditCardVerificationStatus == CreditCardVerificationStatus.BLOCKED) {
							// Credit card is blocked and user will not get his card back, he will get a confirmation instead
							System.out.println(">> UI: Your card is invalid. Your card will be withheld. Please contact your bank.");
						}
					} else {
						// If ATM will fail to read a card it will notify user about this fact and will abort transaction
						System.out
						        .println(">> UI: Failed to read credit card number. Your card will be ejected. Please contact your bank or try again later.");
					}
				} else {
					// If user does not want to continue without printer we finish the transaction
					System.out.println(">> UI: You chose to abort operation. Your card will be ejected now.");
				}
			} else {
				// If user does not want to continue without printer we finish the transaction
				System.out.println(">> UI: This ATM does not have connection to bank. Please try again later.");
			}

			System.out.println("");
			System.out.println("");

			// End transaction to put ATM in idle mode
			atmEngine.endTransaction();
		}

	}

	private static PinCodeVerificationStatus ReadPinCode() {
		PinCodeVerificationStatus status;
		do {
			System.out.print(">> UI: Please enter your PIN code: ");
			String input = null;
			do {
				input = scan.nextLine();
			} while (!ValidationUtilities.isPinCode(input));
			status = atmEngine.verifyPinCode(input);
		} while (status != PinCodeVerificationStatus.OK && status != PinCodeVerificationStatus.FAILED_CARD_LOCKED);

		return status;
	}

	private static WithdrawStatus WithDrawAmount() {
		System.out.println(">> UI: Choose amount to withdraw:");
		System.out.println("1) DKK 100");
		System.out.println("2) DKK 200");
		System.out.println("3) DKK 500");
		System.out.println("4) DKK 1000");
		System.out.println("5) DKK 2000");
		System.out.println("Press 'a' to abort transaction.");

		WithdrawStatus status;
		boolean finishWithdraw = false;
		int amount = 0;
		int attempts = 0;

		// We will try maximum 3 times to select appropriate amount
		do {
			String input = scan.nextLine();

			// Operation will abort if user presses 'a' or tries more than 3 times
			if (input.equals("a") || attempts > 2) {
				status = WithdrawStatus.ABORTED;
				finishWithdraw = true;
			} else {
				switch (Integer.parseInt(input)) {
					case 1:
						amount = 100;
						break;
					case 2:
						amount = 200;
						break;
					case 3:
						amount = 500;
						break;
					case 4:
						amount = 1000;
						break;
					case 5:
						amount = 2000;
						break;
				}
				status = atmEngine.withdraw(amount);

				// If withdraw was successful then cool ( ͡° ͜ʖ ͡°)
				if (status == WithdrawStatus.OK) {
					finishWithdraw = true;
				} else if (status == WithdrawStatus.FAILED_NOT_ENOUGH_FUNDS) {
					// If clients has not enough funds lets ask him to pick another amount
					System.out.println(">> UI: You do not have enough funds on your account. Please try again with smaller amount.");
				} else if (status == WithdrawStatus.FAILED_NOT_ENOUGH_CASH_IN_ATM) {
					// If there is not enough cash in ATM we should also notify customer
					System.out.println(">> UI: This ATM has not enough funds. Please try again with smaller amount.");
				}
			}
			++attempts;
		} while (!finishWithdraw);

		return status;
	}

}
